﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DPS.Prototype.Model;
using DPS.Prototype.PolicyBase.Manager;
using System.Threading;
using DPS.Prototype.PolicyBase.Filters;
namespace DPS.Prototype.PolicyBase
{
    public enum CompleteStatus
    {
        NotStart,
        Processing,
        Suspend,
        Finished
    }
    public abstract class ProdCompetitorBase : IComparable<ProdCompetitorBase>
    {
        private ProdLine _prodLine;

        private List<Capacity> cureentTobeOccupyCapacity;

        private CompleteStatus CurrentStatus;

        protected float CurrentTotalAvailableCapacity
        {
            get
            {
                return this._prodLine.Capacitys.Sum(c => (c.TotalUsage - c.OccupiedUsage));
            }
        }

        private int CurrentCycleNo = 0;

        public ProdLine ProdLine
        {
            get { return this._prodLine; }
        }

        public string CompetitorName
        {
            get { return this._prodLine.LineNo; }
        }

        public List<Capacity> CurrentTobeOccupyCapacity
        {
            get { return this.cureentTobeOccupyCapacity; }
            set { this.cureentTobeOccupyCapacity = value; }
        }

        protected object lockObj = new object();

        private object lockExcutingOrderObj = new object();
        private bool isExcutingOrder = false;

        private string _lastProducedModelName;
        public string LastProducedModelName
        {
            get { return this._lastProducedModelName; }
            protected set { this._lastProducedModelName = value; }
        }

        private Capacity _lastProducedCapacity;
        public Capacity LastProducedCapacity
        {
            get { return this._lastProducedCapacity; }
            protected set { this._lastProducedCapacity = value; }
        }

        private bool _isAbandonAllCycle = false;
        protected bool IsAbandonAllCycle
        {
            get { return this._isAbandonAllCycle; }
            set { this._isAbandonAllCycle = value; }
        }

 

        protected ProdCompetitorBase(ProdLine prodLine)
        {
            this._prodLine = prodLine;
            this.cureentTobeOccupyCapacity = new List<Capacity>();
        }

        //private void ExcuteCompeteProcess()
        //{
        //    if (this.CurrentStatus == CompleteStatus.Finished)
        //    {
        //        return;
        //    }
        //    try
        //    {
        //        if (this.CurrentStatus != CompleteStatus.Processing)
        //        {
        //            lock (lockObj)
        //            {
        //                if (this.CurrentStatus != CompleteStatus.Processing)
        //                {
        //                    this.CurrentStatus = CompleteStatus.Processing;
        //                    SubmitResult submitResult = this.CompeteProcess();
        //                    Submission subMission = new Submission(submitResult, this, this.CurrentCycleNo);
        //                    this.NotifyToPolicyMaker(subMission);
        //                }
        //            }
        //        }
        //    }
        //    finally
        //    {
        //        if (this.CurrentStatus != CompleteStatus.Finished)
        //        {
        //            this.CurrentStatus = CompleteStatus.Suspend;
        //        }
        //    }
        //}

        private void ExcuteCompeteProcess()
        {
            SubmitResult submitResult = this.CompeteProcess();
            Submission subMission = new Submission(submitResult, this, this.CurrentCycleNo);
            this.NotifyToPolicyMaker(subMission);
        }

        protected void NotifyToPolicyMaker(Submission submission)
        {
            PolicyMakerManager.Current.PolicyMaker.ReceiveSubmission(submission);
        }

        public void RecevieOrder(PolicyOrder policyOrder)
        {
            ThreadPool.QueueUserWorkItem((s) => { this.ExcutePolicyOrder(policyOrder); });
            Manager.TrackingManger.Current.Tracking.TrackingReceivingPolicy(policyOrder, this);
        }

        private void ExcutePolicyOrder(PolicyOrder policyOrder)
        {
            try
            {
                if (!isExcutingOrder)
                {
                    lock (this.lockExcutingOrderObj)
                    {
                        if (!isExcutingOrder)
                        {
                            this.isExcutingOrder = true;
                            switch (policyOrder.OrderType)
                            {
                                case OrderType.StartNewCycle:
                                    this.CurrentCycleNo = (int)policyOrder["CycleNo"];
                                    this.cureentTobeOccupyCapacity.Clear();
                                    this.ExcuteCompeteProcess();
                                    break;

                                case OrderType.AbandonThisCycle:
                                    this.cureentTobeOccupyCapacity.ForEach(c =>
                                    {
                                        //Just update to be occupied capacity
                                        c.TobeOccupyUsage = 0.00f;
                                    });
                                    break;

                                case OrderType.ApproveThisCycle:
                                    policyOrder.Submission.Result.Submit();
                                    this.cureentTobeOccupyCapacity.ForEach(c =>
                                    {
                                        //Occupy capacity and update to be occupied capacity
                                        c.OccupiedUsage = c.OccupiedUsage + c.TobeOccupyUsage;
                                        c.TobeOccupyUsage = 0.00f;
                                    });
                                    this._lastProducedModelName = policyOrder.Submission.Result.WorkOrder.Model;
                                    this._lastProducedCapacity = this.cureentTobeOccupyCapacity.Last();
                                    break;
                            }
                            this.isExcutingOrder = false;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                this.isExcutingOrder = false;
            }
        }

        protected bool CheckIsFullCapacity()
        {
            DateTime latestDate = SystemSettings.SystemStartTime.AddHours(SystemSettings.WorkOrderRangeHours);
            var availableCapacity = this._prodLine.Capacitys.Where(c => (c.CapacityStatus != CapacityStatus.TotalOcuppy) && c.StartTime < latestDate);
            return availableCapacity.Count() == 0;
        }

        public int CompareTo(ProdCompetitorBase other)
        {
            return this.ProdLine.CompareTo(other.ProdLine);
        }

        protected WorkOrder FindWorkOrderToBeProduced()
        {
            WorkOrder order = null;
            List<string> models = this.ProdLine.Models;
            var matchedOrders = WorkOrderPool.WorkOrderList.Where(wo => { return models.Contains(wo.Model); }).ToList();
            foreach (WorkOrderFiltersBase filter in this.OrderFilters)
            {
                matchedOrders = filter.Filter(matchedOrders, this);
            }

            if (matchedOrders.Count() > 0)
            {
                order = matchedOrders.First();
            }
            return order;
        }

        #region Abstract Members

        protected abstract SubmitResult CompeteProcess();

        public abstract List<WorkOrderFiltersBase> OrderFilters { get; }

        #endregion
    }
}
